package com.youran.restful.webprinter.util;

import java.util.UUID;
import java.util.zip.CRC32;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Generator {
	
	private static Logger logger = LoggerFactory.getLogger(Generator.class);
	
	private static final String LOCK_KEY = "LOCK";
	
	private static CRC32 crc32 = new CRC32();

	public static String generatId(HttpServletRequest request) {
		String hostClient = getIpAddress(request);
		
		synchronized (LOCK_KEY) {
			crc32.reset();
			crc32.update(hostClient.getBytes());
			String genId = String.valueOf(crc32.getValue());
			logger.info("客户端ip={}计算得到文档子目录名称={}", hostClient, genId);
			return genId;
		}
	}
	
	/**
	* 获取访问者IP
	* 
	* 在一般情况下使用Request.getRemoteAddr()即可，但是经过nginx等反向代理软件后，这个方法会失效。
	* 
	* 本方法先从Header中获取X-Real-IP，如果不存在再从X-Forwarded-For获得第一个IP(用,分割)，
	* 如果还不存在则调用Request .getRemoteAddr()。
	* 
	* @param request
	* @return
	*/
	public static synchronized String getIpAddr(HttpServletRequest request) {
		try {
			String ip = request.getHeader("X-Real-IP");
			logger.info("===0===== ip={} \n{}", ip, request);
			ip = request.getHeader("x-real-ip");
			logger.info("===00===== ip={} \n{}", ip, request);
			ip = request.getHeader("x-forwarded-for");
			logger.info("===01===== ip={} \n{}", ip, request);
			ip = request.getHeader("WL-Proxy-Client-IP");
			logger.info("===02===== ip={} \n{}", ip, request);
			ip = request.getHeader("Proxy-Client-IP");
			logger.info("===03===== ip={} \n{}", ip, request);
			if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
				return ip;
			}
			ip = request.getHeader("X-Forwarded-For");
			logger.info("===1===== ip={}", ip);
			if (StringUtils.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
				// 多次反向代理后会有多个IP值，第一个为真实IP。
				int index = ip.indexOf(',');
				if (index != -1) {
					return ip.substring(0, index);
				} else {
					return ip;
				}
			} else {
				return request.getRemoteAddr();
			}
		} catch(Exception e) {
			logger.error("获取客户端ip异常:{}", e);
		}
		return UUID.randomUUID().toString();
	}
	
	/** 
     * 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址; 
     *  
     * @param request 
     * @return 
     * @throws IOException 
     */  
	public static String getIpAddress(HttpServletRequest request) {
		// 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址

		String ip = request.getHeader("X-Forwarded-For");
		logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip={}", ip);

		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("Proxy-Client-IP");
				logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip={}", ip);

			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("WL-Proxy-Client-IP");
				logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip={}", ip);

			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_CLIENT_IP");
				logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip={}", ip);

			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getHeader("HTTP_X_FORWARDED_FOR");
				logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip={}", ip);

			}
			if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
				logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip={}", ip);

			}
		} else if (ip.length() > 15) {
			String[] ips = ip.split(",");
			for (int index = 0; index < ips.length; index++) {
				String strIp = (String) ips[index];
				if (!("unknown".equalsIgnoreCase(strIp))) {
					ip = strIp;
					break;
				}
			}
		}
		logger.info("result ip={}", ip);
		return ip;
	}
}
